package demo1;

import org.junit.Test;

import java.util.*;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @author lilingzhi
 * @since 2022/12/21 17:02
 */
public class ReduceDemo {

    /**
     * 通常reduce变体
     */
    @Test
    public void reduceTest(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        Integer reduce = list.stream().reduce(100, (f1, f2) -> f1 * f2);
        System.out.println(reduce);
        // 不提供初始值 , 则返回optional ,可能不存在结果值,或者结果值null
        Optional<Integer> reduce1 = list.stream().reduce((f1, f2) -> f1 * f2);
        reduce1.ifPresent(System.out::println);

    }

    @Test
    public void test(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        IntSummaryStatistics intSummaryStatistics = list.stream().mapToInt(i -> i).summaryStatistics();
    }

    @Test
    public void test2(){
        IntStream intStream = IntStream.rangeClosed(1, 100);
//        intStream.boxed().collect(Collectors.toList()).forEach(System.out::println);
        OptionalInt reduce = intStream.reduce((x1, x2) -> x1 * x2);
        reduce.ifPresent(System.out::println);
    }

    /**
     * 递归
     */
    @Test
    public void test3(){
        List<Integer> collect = Stream.iterate(new int[]{0, 1}, i -> new int[]{i[1], i[0] + i[1]})
                .limit(11).map(arr -> arr[0]).collect(Collectors.toList());
        System.out.println(collect);
    }


    /**
     * java 递归方式
     */
    @Test
    public void test4(){
        int fun = fun(10);
        System.out.println(fun);
    }


    /**
     * iterate 相较于 generate  而言  ,iterate 的元素并没由发生状态的修改,而generate 反而不断改变现有，并且记录之前的元素
     */
    @Test
    public void generateTest(){
//        Stream.generate(Math::random)
//                .limit(11)
//                .forEach(System.out::println);
        IntStream.generate(new IntSupplier() {
            private int start = 0;
            private int end  = 1;
            @Override
            public int getAsInt() {
               int oldStart = this.start;
               int oldEnd = this.end;
               this.end = oldEnd + oldStart;
               this.start = oldEnd;
               return oldStart;
            }
        }
        ).limit(10).forEach(System.out::println);
    }


    public int fun(int num){
        if (num == 0) {
            return 0;
        }else if (num ==1){
            return 1;
        }else{
         return fun(num - 1 ) + fun(num - 2);
        }
    }
}
